home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / trace / tcpdump-2.2.1 / print-nfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-31  |  10.5 KB  |  467 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] =
  24.     "@(#) $Header: print-nfs.c,v 1.24 92/01/31 12:27:46 mccanne Exp $ (LBL)";
  25. #endif
  26.  
  27. #include <stdio.h>
  28. #include <sys/param.h>
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31. #include <net/if.h>
  32. #include <netinet/in.h>
  33. #include <netinet/if_ether.h>
  34. #include <netinet/in_systm.h>
  35. #include <netinet/ip.h>
  36. #include <netinet/ip_var.h>
  37.  
  38. #include <sys/time.h>
  39. #include <errno.h>
  40. #include <rpc/types.h>
  41. #include <rpc/auth.h>
  42. #include <rpc/auth_unix.h>
  43. #include <rpc/svc.h>
  44. #include <rpc/xdr.h>
  45. #include <rpc/rpc_msg.h>
  46.  
  47. #include <ctype.h>
  48.  
  49. #include "interface.h"
  50. /* These must come after interface.h for BSD. */
  51. #if BSD >= 199006
  52. #include <sys/ucred.h>
  53. #include <nfs/nfsv2.h>
  54. #endif
  55. #include <nfs/nfs.h>
  56.  
  57. #include "addrtoname.h"
  58. #include "extract.h"
  59.  
  60. static void nfs_printfh();
  61. static void nfs_printfn();
  62.  
  63. #if BYTE_ORDER == LITTLE_ENDIAN
  64. /*
  65.  * Byte swap an array of n words.
  66.  * Assume input is word-aligned.
  67.  * Check that buffer is bounded by "snapend".
  68.  */
  69. static void
  70. bswap(bp, n)
  71.     register u_long *bp;
  72.     register u_int n;
  73. {
  74.     register int nwords = ((char *)snapend - (char *)bp) / sizeof(*bp);
  75.  
  76.     if (nwords > n)
  77.         nwords = n;
  78.     for (; --nwords >= 0; ++bp)
  79.         *bp = ntohl(*bp);
  80. }
  81. #endif
  82.  
  83. void
  84. nfsreply_print(rp, length, ip)
  85.     register struct rpc_msg *rp;
  86.     int length;
  87.     register struct ip *ip;
  88. {
  89. #if BYTE_ORDER == LITTLE_ENDIAN
  90.     bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long));
  91. #endif
  92.     if (!nflag)
  93.         (void)printf("%s.nfs > %s.%x: reply %s %d",
  94.                  ipaddr_string(&ip->ip_src),
  95.                  ipaddr_string(&ip->ip_dst),
  96.                  rp->rm_xid,
  97.                  rp->rm_reply.rp_stat == MSG_ACCEPTED? "ok":"ERR",
  98.                  length);
  99.     else
  100.         (void)printf("%s.%x > %s.%x: reply %s %d",
  101.                  ipaddr_string(&ip->ip_src),
  102.                  NFS_PORT,
  103.                  ipaddr_string(&ip->ip_dst),
  104.                  rp->rm_xid,
  105.                  rp->rm_reply.rp_stat == MSG_ACCEPTED? "ok":"ERR",
  106.                  length);
  107. }
  108.  
  109. /*
  110.  * Return a pointer to the first file handle in the packet.
  111.  * If the packet was truncated, return 0.
  112.  */
  113. static u_long *
  114. parsereq(rp, length)
  115.     register struct rpc_msg *rp;
  116.     register int length;
  117. {
  118.     register u_long *dp = (u_long *)&rp->rm_call.cb_cred;
  119.     register u_long *ep = (u_long *)snapend;
  120.  
  121.     /* 
  122.      * find the start of the req data (if we captured it) 
  123.      * note that dp[1] was already byte swapped by bswap()
  124.      */
  125.     if (dp < ep && dp[1] < length) {
  126.         dp += (dp[1] + (2*sizeof(u_long) + 3)) / sizeof(u_long);
  127.         if ((dp < ep) && (dp[1] < length)) {
  128.             dp += (dp[1] + (2*sizeof(u_long) + 3)) /
  129.                 sizeof(u_long);
  130.             if (dp < ep)
  131.                 return (dp);
  132.         }
  133.     }
  134.     return (0);
  135. }
  136.  
  137. /*
  138.  * Print out an NFS file handle and return a pointer to following word.
  139.  * If packet was truncated, return 0.
  140.  */
  141. static u_long *
  142. parsefh(dp)
  143.     register u_long *dp;
  144. {
  145.     if (dp + 8 <= (u_long *)snapend) {
  146.         nfs_printfh(dp);
  147.         return (dp + 8);
  148.     }
  149.     return (0);
  150. }
  151.  
  152. /*
  153.  * Print out a file name and return pointer to longword past it.
  154.  * If packet was truncated, return 0.
  155.  */
  156. static u_long *
  157. parsefn(dp)
  158.     register u_long *dp;
  159. {
  160.     register int len;
  161.     register u_char *cp;
  162.  
  163.     /* Bail if we don't have the string length */
  164.     if ((u_char *)dp > snapend - sizeof(*dp))
  165.         return(0);
  166.  
  167.     /* Fetch string length; convert to host order */
  168.     len = *dp++;
  169.     NTOHL(len);
  170.  
  171.     cp = (u_char *)dp;
  172.     /* Update long pointer (NFS filenames are padded to long) */
  173.     dp += ((len + 3) & ~3) / sizeof(*dp);
  174.     if ((u_char *)dp > snapend)
  175.         return (0);
  176.     nfs_printfn(cp, len);
  177.  
  178.     return (dp);
  179. }
  180.  
  181. /*
  182.  * Print out file handle and file name.
  183.  * Return pointer to longword past file name.
  184.  * If packet was truncated (or there was some other error), return 0.
  185.  */
  186. static u_long *
  187. parsefhn(dp)
  188.     register u_long *dp;
  189. {
  190.     dp = parsefh(dp);
  191.     if (dp == 0)
  192.         return (0);
  193.     putchar(' ');
  194.     return (parsefn(dp));
  195. }
  196.  
  197. void
  198. nfsreq_print(rp, length, ip)
  199.     register struct rpc_msg *rp;
  200.     int length;
  201.     register struct ip *ip;
  202. {
  203.     register u_long *dp;
  204.     register u_char *ep = snapend;
  205. #define TCHECK(p, l) if ((u_char *)(p) > ep - l) break
  206.  
  207. #if BYTE_ORDER == LITTLE_ENDIAN
  208.     bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long));
  209. #endif
  210.  
  211.     if (!nflag)
  212.         (void)printf("%s.%x > %s.nfs: %d",
  213.                  ipaddr_string(&ip->ip_src),
  214.                  rp->rm_xid,
  215.                  ipaddr_string(&ip->ip_dst),
  216.                  length);
  217.     else
  218.         (void)printf("%s.%x > %s.%x: %d",
  219.                  ipaddr_string(&ip->ip_src),
  220.                  rp->rm_xid,
  221.                  ipaddr_string(&ip->ip_dst),
  222.                  NFS_PORT,
  223.                  length);
  224.  
  225.     switch (rp->rm_call.cb_proc) {
  226. #ifdef NFSPROC_NOOP
  227.     case NFSPROC_NOOP:
  228.         printf(" nop");
  229.         return;
  230. #else
  231. #define NFSPROC_NOOP -1
  232. #endif
  233.     case RFS_NULL:
  234.         printf(" null");
  235.         return;
  236.  
  237.     case RFS_GETATTR:
  238.         printf(" getattr");
  239.         if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
  240.             return;
  241.         break;
  242.  
  243.     case RFS_SETATTR:
  244.         printf(" setattr");
  245.         if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
  246.             return;
  247.         break;
  248.  
  249. #if RFS_ROOT != NFSPROC_NOOP
  250.     case RFS_ROOT:
  251.         printf(" root");
  252.         break;
  253. #endif
  254.     case RFS_LOOKUP:
  255.         printf(" lookup");
  256.         if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
  257.             return;
  258.         break;
  259.  
  260.     case RFS_READLINK:
  261.         printf(" readlink");
  262.         if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
  263.             return;
  264.         break;
  265.  
  266.     case RFS_READ:
  267.         printf(" read");
  268.         if ((dp = parsereq(rp, length)) != 0 &&
  269.             (dp = parsefh(dp)) != 0) {
  270.             TCHECK(dp, 3 * sizeof(*dp));
  271.             printf(" %lu (%lu) bytes @ %lu",
  272.                    ntohl(dp[1]), ntohl(dp[2]), ntohl(dp[0]));
  273.             return;
  274.         }
  275.         break;
  276.  
  277. #if RFS_WRITECACHE != NFSPROC_NOOP
  278.     case RFS_WRITECACHE:
  279.         printf(" writecache");
  280.         if ((dp = parsereq(rp, length)) != 0 &&
  281.             (dp = parsefh(dp)) != 0) {
  282.             TCHECK(dp, 4 * sizeof(*dp));
  283.             printf(" %lu (%lu) bytes @ %lu (%lu)",
  284.                    ntohl(dp[3]), ntohl(dp[2]),
  285.                    ntohl(dp[1]), ntohl(dp[0]));
  286.             return;
  287.         }
  288.         break;
  289. #endif
  290.     case RFS_WRITE:
  291.         printf(" write");
  292.         if ((dp = parsereq(rp, length)) != 0 &&
  293.             (dp = parsefh(dp)) != 0) {
  294.             TCHECK(dp, 4 * sizeof(*dp));
  295.             printf(" %lu (%lu) bytes @ %lu (%lu)",
  296.                    ntohl(dp[3]), ntohl(dp[2]),
  297.                    ntohl(dp[1]), ntohl(dp[0]));
  298.             return;
  299.         }
  300.         break;
  301.  
  302.     case RFS_CREATE:
  303.         printf(" create");
  304.         if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
  305.             return;
  306.         break;
  307.  
  308.     case RFS_REMOVE:
  309.         printf(" remove");
  310.         if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
  311.             return;
  312.         break;
  313.  
  314.     case RFS_RENAME:
  315.         printf(" rename");
  316.         if ((dp = parsereq(rp, length)) != 0 && 
  317.             (dp = parsefhn(dp)) != 0) {
  318.             fputs(" ->", stdout);
  319.             if (parsefhn(dp) != 0)
  320.                 return;
  321.         }
  322.         break;
  323.  
  324.     case RFS_LINK:
  325.         printf(" link");
  326.         if ((dp = parsereq(rp, length)) != 0 &&
  327.             (dp = parsefh(dp)) != 0) {
  328.             fputs(" ->", stdout);
  329.             if (parsefhn(dp) != 0)
  330.                 return;
  331.         }
  332.         break;
  333.  
  334.     case RFS_SYMLINK:
  335.         printf(" symlink");
  336.         if ((dp = parsereq(rp, length)) != 0 &&
  337.             (dp = parsefhn(dp)) != 0) {
  338.             fputs(" -> ", stdout);
  339.             if (parsefn(dp) != 0)
  340.                 return;
  341.         }
  342.         break;
  343.  
  344.     case RFS_MKDIR:
  345.         printf(" mkdir");
  346.         if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
  347.             return;
  348.         break;
  349.  
  350.     case RFS_RMDIR:
  351.         printf(" rmdir");
  352.         if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
  353.             return;
  354.         break;
  355.  
  356.     case RFS_READDIR:
  357.         printf(" readdir");
  358.         if ((dp = parsereq(rp, length)) != 0 &&
  359.             (dp = parsefh(dp)) != 0) {
  360.             TCHECK(dp, 2 * sizeof(*dp));
  361.             printf(" %lu bytes @ %lu", ntohl(dp[1]), ntohl(dp[0]));
  362.             return;
  363.         }
  364.         break;
  365.  
  366.     case RFS_STATFS:
  367.         printf(" statfs");
  368.         if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
  369.             return;
  370.         break;
  371.  
  372.     default:
  373.         printf(" proc-%lu", rp->rm_call.cb_proc);
  374.         return;
  375.     }
  376.     fputs(" [|nfs]", stdout);
  377. #undef TCHECK
  378. }
  379.  
  380. /*
  381.  * Print out an NFS file handle.
  382.  * We assume packet was not truncated before the end of the
  383.  * file handle pointed to by dp.
  384.  */
  385. static void
  386. nfs_printfh(dp)
  387.     register u_long *dp;
  388. {
  389.     /*
  390.      * take a wild guess at the structure of file handles.
  391.      * On sun 3s, there are 2 longs of fsid, a short
  392.      * len == 8, a long of inode & a long of generation number.
  393.      * On sun 4s, the len == 10 & there are 2 bytes of
  394.      * padding immediately following it.
  395.      */
  396.     if (dp[2] == 0xa0000) {
  397.         if (dp[1])
  398.             (void) printf(" fh %ld.%ld.%lu", dp[0], dp[1], dp[3]);
  399.         else
  400.             (void) printf(" fh %ld.%ld", dp[0], dp[3]);
  401.     } else if ((dp[2] >> 16) == 8)
  402.         /*
  403.          * 'dp' is longword aligned, so we must use the extract
  404.          * macros below for dp+10 which cannot possibly be aligned.
  405.          */
  406.         if (dp[1])
  407.             (void) printf(" fh %ld.%ld.%lu", dp[0], dp[1],
  408.                       EXTRACT_LONG((u_char *)dp + 10));
  409.         else
  410.             (void) printf(" fh %ld.%ld", dp[0],
  411.                       EXTRACT_LONG((u_char *)dp + 10));
  412.     /* On Ultrix pre-4.0, three longs: fsid, fno, fgen and then zeros */
  413.     else if (dp[3] == 0) {
  414.         (void)printf(" fh %d,%d/%ld.%ld", major(dp[0]), minor(dp[0]),
  415.                  dp[1], dp[2]);
  416.     }
  417.     /*
  418.      * On Ultrix 4.0,
  419.      * five longs: fsid, fno, fgen, eno, egen and then zeros
  420.      */
  421.     else if (dp[5] == 0) {
  422.         (void)printf(" fh %d,%d/%ld.%ld", major(dp[0]), minor(dp[0]),
  423.                  dp[1], dp[2]);
  424.         if (vflag) {
  425.             /* print additional info */
  426.             (void)printf("[%ld.%ld]", dp[3], dp[4]);
  427.         }
  428.     }
  429.     else
  430.         (void) printf(" fh %lu.%lu.%lu.%lu",
  431.             dp[0], dp[1], dp[2], dp[3]);
  432. }
  433.  
  434. /*
  435.  * Print out an NFS filename.
  436.  * Assumes that len bytes from cp are present in packet.
  437.  */
  438. static void
  439. nfs_printfn(cp, len)
  440.     register u_char *cp;
  441.     register int len;
  442. {
  443.     register char c;
  444.  
  445.     /* Sanity */
  446.     if (len >= 64) {
  447.         fputs("[\">]", stdout);
  448.         return;
  449.     }
  450.     /* Print out the filename */
  451.     putchar('"');
  452.     while (--len >= 0) {
  453.         c = toascii(*cp++);
  454.         if (!isascii(c)) {
  455.             c = toascii(c);
  456.             putchar('M');
  457.             putchar('-');
  458.         }
  459.         if (!isprint(c)) {
  460.             c ^= 0x40;    /* DEL to ?, others to alpha */
  461.             putchar('^');
  462.         }
  463.         putchar(c);
  464.     }
  465.     putchar('"');
  466. }
  467.